package analiseSintatica.Regras.Expressoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import java.util.LinkedList;

import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;

/**
 * Contem as regras para a analise sintatica
 * @author nathy
 * nathy
 */
public class RegraPrimario extends Regra {

    protected static Regra instancia;
    protected String estrutura = "<primario> ::= numeroInteiro | numeroFlutuante | charconst";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraPrimario() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraPrimario getInstance() {
        if (instancia == null) {
            instancia = new RegraPrimario();
        }
        return (RegraPrimario) instancia;
    }

    /**
     * Realiza analise sintatica
     * @param listaTokens - Tokens do codigo
     * @return - Arvore sintatica
     * @throws Exception
     */
    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

        TiposSemanticos tipos = new TiposSemanticos();
        
        LinkToken token = listaTokens.getFirst();
        if(listaContem(RegraPrimario.getInstance().getPrimeiro(), listaTokens.getFirst())){
                listaTokens.removeFirst().getLexema();
                
                
                //ANALISE SEMANTICA
                
                if(token.getToken().equals("numero_inteiro"))
                    tipos.addTipos(new TipoSemantico("int",token.getLinha()));
                else if(token.getToken().equals("numero_flutuante"))
                     tipos.addTipos(new TipoSemantico("float",token.getLinha()));
                else
                     tipos.addTipos(new TipoSemantico("char",token.getLinha()));

        }
        
        else{
            tipos = null;
            ErroSintaticoException e = new ErroSintaticoException();
            e.addErros("Falta tipo primitivo esperado antes do token " + listaTokens.getFirst().getLexema(), estrutura, listaTokens.getFirst().getLinha());
            throw e;
        }
        
        return tipos;
    }

    @Override
    protected void setPrimeiro() {
        this.primeiro.add("numero_inteiro");
        this.primeiro.add("numero_flutuante");
        this.primeiro.add("charconst");
    }

   
}
